/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024.
 * Description: rtos enhancement of signal
 * Author: zhangningyi
 * Create: 2024/07/08
 */
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/signal.h>
#include <linux/rtos_dump.h>
#include <internal/rtos_signal.h>

#define DUMP_MEM_SIZE 128

static void show_vma_info(struct vm_area_struct *vma, const char *vma_msg)
{
	if (vma) {
		do_show_user_data(vma->vm_start, DUMP_MEM_SIZE, vma_msg);
		pr_err("%s start from %lx and end at %lx\r\n", vma_msg,
		       vma->vm_start, vma->vm_end);
	}
}

/*
 * Check the result of sigframe. Print necessary log if failed, including
 * - Current task and signal info
 * - Current and the previous/next vma info
 */
void check_sigframe_valid(int ret, struct ksignal *ksig, struct pt_regs *regs)
{
	struct task_struct *task = current;
	unsigned long sp_addr;
	struct vm_area_struct *vma;

	if (!ret)
		return;

	sp_addr = user_stack_pointer(regs);
	vma = find_vma(task->mm, sp_addr);

	pr_err("SigFrame not valid: PID=%d, Command=%s, SP=%lx, signo=%d, sigcode=%d\n",
	       task->pid, task->comm, sp_addr, ksig->info.si_signo,
	       ksig->info.si_code);
	do_show_user_data(sp_addr, DUMP_MEM_SIZE, "Stacks at SP");
	show_vma_info(vma, "Current VMA");
	if (vma) {
		show_vma_info(vma->vm_prev, "Previous VMA");
		show_vma_info(vma->vm_next, "Next VMA");
	}
}
